/*
 * Copyright 2012 Rivoli team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.rivoli.document.renderer.text

import com.googlecode.rivoli.document.Cell
import com.googlecode.rivoli.document.Row
import com.googlecode.rivoli.document.Table
import com.googlecode.rivoli.model.classhierarchy.RendererFor

@RendererFor(Table)
class TableRenderer extends AbstractTextRenderer<Table> {
	@Override
	protected List<String> render(Table table, int width) {
		List<Integer> columnWidths = getColumnWidths(table, width)

		List<String> renderedTable = [createBorder(columnWidths)]

		table.rows.each {Row row ->
			renderedTable.addAll(renderRow(row, columnWidths))
			renderedTable << createBorder(columnWidths)
		}

		renderedTable
	}

	List<Integer> getColumnWidths(Table table, int width) {
		int cellCount = table.rows[0].cells.size()

		List<Integer> columnWidths = [0] * cellCount

		for (int i in 0..<width - (cellCount + 1)) {
			columnWidths[i % columnWidths.size()]++
		}

		columnWidths
	}

	private String createBorder(List<Integer> columnWidths) {
		columnWidths.inject('+') {String border, int columnWidth ->
			"${border}${'-' * columnWidth}+"
		}
	}

	private List<String> renderRow(Row row, List<Integer> columnWidths) {
		List<RenderedCell> renderedCells = []

		row.cells.eachWithIndex{Cell cell, int index ->
			int columnWidth = columnWidths[index]
			renderedCells << new RenderedCell(lines: getRenderer(cell).render(getElement(cell), columnWidth), width: columnWidth)
		}

		int maxLineCount = renderedCells.max {it.lineCount}.lineCount

		List<String> renderedRow = []

		for (int i in 0..<maxLineCount) {
			renderedRow << renderedCells.inject('|') {String line, RenderedCell renderedCell ->
				"${line}${renderedCell.getLine(i)}|"
			}
		}

		renderedRow
	}

	private static class RenderedCell {
		List<String> lines
		int width

		int getLineCount() {
			lines.size()
		}

		String getLine(int index) {
			String line = (index < lineCount) ? lines[index] : ''

			"${line}${' ' * (width - line.length())}"
		}
	}
}